package com.uzai.console.service.user.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.extra.cglib.CglibUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.uzai.common.entity.User;
import com.uzai.common.entity.WechatUser;
import com.uzai.common.entity.WxpubUser;
import com.uzai.common.entity.WxworkUser;
import com.uzai.common.exception.BusinessException;
import com.uzai.console.constant.ES.ElasticsearchUtil;
import com.uzai.console.dto.user.blacklist.marketingrewards.MarketingRewardsBlackListBatchDto;
import com.uzai.console.dto.user.blacklist.marketingrewards.MarketingRewardsBlackListOptDto;
import com.uzai.console.dto.user.blacklist.marketingrewards.MarketingRewardsBlackListQuery;
import com.uzai.console.entity.Device;
import com.uzai.console.entity.es.MarketingRewardsBlackListDocument;
import com.uzai.console.mapper.WechatUserMapper;
import com.uzai.console.mapper.WxpubUserMapper;
import com.uzai.console.mapper.WxworkUserMapper;
import com.uzai.console.mapper.es.EsMarketingRewardsBlackListRepository;
import com.uzai.console.service.device.DeviceService;
import com.uzai.console.service.user.MarketingRewardsBlackListService;
import com.uzai.console.service.user.UserService;
import com.uzai.console.vo.user.blacklist.marketingrewards.MarketingRewardsBlackListVO;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @author mingyang.chen create in 2023/4/13 18:46
 */
@Component
public class MarketingRewardsBlackListServiceImpl implements MarketingRewardsBlackListService {

    @Autowired
    private ElasticsearchUtil elasticsearchUtil;

    @Autowired
    private WechatUserMapper wechatUserMapper;

    @Autowired
    private WxpubUserMapper wxpubUserMapper;

    @Autowired
    private WxworkUserMapper wxworkUserMapper;

    @Autowired
    private DeviceService deviceService;

    @Autowired
    private UserService userService;

    @Autowired
    private EsMarketingRewardsBlackListRepository marketingRewardsBlackListRepository;

    @Override
    public Page<MarketingRewardsBlackListVO> page(MarketingRewardsBlackListQuery query) {

        ElasticsearchRestTemplate elasticsearchRestTemplate = elasticsearchUtil.elasticsearchRestTemplate();

        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();


        //运营商ID
        queryBuilder.must(QueryBuilders.termQuery("merId", query.getMerId()));

        if (StringUtils.isNotBlank(query.getWxid())) {
            queryBuilder.must(QueryBuilders.termQuery("wxid", query.getWxid()));
        }

        if (Objects.nonNull(query.getUserId())) {
            String wxId = getWxId(query.getUserId(), query.getMerId());
            if (StringUtils.isNotBlank(wxId)) {
                queryBuilder.must(QueryBuilders.termQuery("wxid", wxId));
            }
        }

        //设备类型
        if (StringUtils.isNotBlank(query.getDeviceType())) {
            queryBuilder.must(QueryBuilders.termQuery("deviceType", query.getDeviceType()));
        }

        //高亮字段
        String highlightField = null;

        //微信昵称
        if (StringUtils.isNotBlank(query.getNickName())) {
            queryBuilder.must(QueryBuilders.matchQuery("nickName", query.getNickName()));
            highlightField = "nickName";
        }

        Integer current = query.getCurrent();
        PageRequest of = PageRequest.of(current > 0 ? current - 1 : current, query.getSize());
        FieldSortBuilder sort = SortBuilders.fieldSort("createTime").order(SortOrder.DESC);
        NativeSearchQuery condition = new NativeSearchQueryBuilder().withQuery(queryBuilder).withPageable(of).withSort(sort).build();

        SearchHits<MarketingRewardsBlackListDocument> searchHits = elasticsearchRestTemplate.search(condition, MarketingRewardsBlackListDocument.class);

        List<MarketingRewardsBlackListVO> records = new ArrayList<>(searchHits.getSearchHits().size());

        for (SearchHit<MarketingRewardsBlackListDocument> searchHit : searchHits.getSearchHits()) {
            MarketingRewardsBlackListDocument item = searchHit.getContent();
            MarketingRewardsBlackListVO record = CglibUtil.copy(item, MarketingRewardsBlackListVO.class);
            Device device = deviceService.findDeviceInfoByDeviceUniqueId(item.getDeviceUniqueId(), item.getDeviceType(), query.getMerId());
            if (Objects.nonNull(device)) {
                record.setDeviceId(device.getDeviceId());
                record.setDeviceName(device.getDeviceName());
                record.setDeviceRemark(device.getDeviceRemark());
            }
            User user = userService.findUserInfoByWxid(query.getMerId(), record.getWxid(), record.getDeviceType());
            if (Objects.nonNull(user)) {
                record.setUserId(user.getId());
            }
            records.add(record);
        }

        Page<MarketingRewardsBlackListVO> result = new Page<>(current, query.getSize(), searchHits.getTotalHits());
        result.setRecords(records);
        return result;
    }

    private String getWxId(Long userId, Long merId) {
        WechatUser wechatUser = wechatUserMapper.selectById(userId, merId);
        if (Objects.nonNull(wechatUser)) {
            return wechatUser.getWxid();
        }
        WxpubUser wxpubUser = wxpubUserMapper.selectById(userId, merId);
        if (Objects.nonNull(wxpubUser)) {
            return wxpubUser.getWxid();
        }
        WxworkUser wxworkUser = wxworkUserMapper.selectById(userId, merId);
        if (Objects.nonNull(wxworkUser)) {
            return wxworkUser.getWxid();
        }
        return null;
    }

    @Override
    public Boolean add(MarketingRewardsBlackListOptDto optDto) {

        if (StringUtils.isBlank(optDto.getWxid())) {
            throw new BusinessException("请输入微信id/会员id");
        }

        //会员信息
        String wxid = optDto.getWxid();

        User user = StringUtils.isNumeric(wxid)
                ? userService.findUserInfo(Long.valueOf(wxid), null, optDto.getMerId())
                : userService.findUserInfoByWxid(optDto.getMerId(), wxid, null
        );

        if (Objects.isNull(user)) {
            throw new BusinessException("微信id/会员id在系统中不存在");
        }

        //id为merId_wxid
        wxid = user.getBizUserId();

        MarketingRewardsBlackListDocument rewardsBlackListDocument = new MarketingRewardsBlackListDocument();
        rewardsBlackListDocument.setId(optDto.getMerId() + "_" + wxid);
        rewardsBlackListDocument.setMerId(optDto.getMerId());
        rewardsBlackListDocument.setDeviceUniqueId(user.getDeviceUniqueId());
        rewardsBlackListDocument.setDeviceType(user.getDeviceType());
        rewardsBlackListDocument.setWxid(wxid);
        rewardsBlackListDocument.setNickName(user.getNickName());
        rewardsBlackListDocument.setHeadImg(user.getHeadImg());
        rewardsBlackListDocument.setSubNotPassFriend(optDto.getSubNotPassFriend());
        rewardsBlackListDocument.setRemark(optDto.getRemark());

        int now = (int) (DateTime.now().getTime() / 1000L);
        rewardsBlackListDocument.setCreateTime(now);
        rewardsBlackListDocument.setUpdateTime(now);
        //增加黑名单
        marketingRewardsBlackListRepository.save(rewardsBlackListDocument);
        return true;
    }

    @Override
    public Boolean addHandleRemarkIfPresent(MarketingRewardsBlackListOptDto optDto) {
        if (StringUtils.isBlank(optDto.getWxid())) {
            throw new BusinessException("请输入微信id/会员id");
        }

        //会员信息
        String wxid = optDto.getWxid();

        User user = StringUtils.isNumeric(wxid)
                ? userService.findUserInfo(Long.valueOf(wxid), null, optDto.getMerId())
                : userService.findUserInfoByWxid(optDto.getMerId(), wxid, null
        );

        if (Objects.isNull(user)) {
            throw new BusinessException("微信id/会员id在系统中不存在");
        }

        //id为merId_wxid
        wxid = user.getBizUserId();

        MarketingRewardsBlackListDocument exists = marketingRewardsBlackListRepository.findById(optDto.getMerId() + "_" + wxid).orElse(null);

        MarketingRewardsBlackListDocument rewardsBlackListDocument = new MarketingRewardsBlackListDocument();
        rewardsBlackListDocument.setId(optDto.getMerId() + "_" + wxid);
        rewardsBlackListDocument.setMerId(optDto.getMerId());
        rewardsBlackListDocument.setDeviceUniqueId(user.getDeviceUniqueId());
        rewardsBlackListDocument.setDeviceType(user.getDeviceType());
        rewardsBlackListDocument.setWxid(wxid);
        rewardsBlackListDocument.setNickName(user.getNickName());
        rewardsBlackListDocument.setHeadImg(user.getHeadImg());
        rewardsBlackListDocument.setSubNotPassFriend(optDto.getSubNotPassFriend());

        if (StringUtils.isBlank(optDto.getRemark()) && Objects.nonNull(exists)) {
            rewardsBlackListDocument.setRemark(exists.getRemark());
        } else {
            rewardsBlackListDocument.setRemark(optDto.getRemark());
        }

        int now = (int) (DateTime.now().getTime() / 1000L);
        rewardsBlackListDocument.setCreateTime(now);
        rewardsBlackListDocument.setUpdateTime(now);
        //增加黑名单
        marketingRewardsBlackListRepository.save(rewardsBlackListDocument);
        return true;
    }

    @Override
    public Boolean remove(Long merId, String id) {
        String combinationId = merId + "_" + id;
        return remove(combinationId);
    }

    @Override
    public Boolean remove(String id) {
        marketingRewardsBlackListRepository.deleteById(id);
        return true;
    }

    @Override
    public String isInBlackList(String wxid, Long merId) {
        MarketingRewardsBlackListDocument document = getById(wxid, merId);
        if (Objects.nonNull(document)) {
            return document.getId();
        }
        return null;
    }

    @Override
    public void addOrRemoveByFlag(Long merId, String wxId, String remark, Integer flag) {
        if (Objects.equals(flag, 0)) {
            this.remove(merId, wxId);
        }
        //
        else if (Objects.equals(flag, 1)) {
            MarketingRewardsBlackListOptDto marketingRewardsBlackListOptDto = new MarketingRewardsBlackListOptDto();
            marketingRewardsBlackListOptDto.setWxid(wxId);
            marketingRewardsBlackListOptDto.setRemark(remark);
            marketingRewardsBlackListOptDto.setMerId(merId);
            this.add(marketingRewardsBlackListOptDto);
        }
    }

    @Override
    public void addOrRemoveByFlag(Long merId, String wxId, String remark, Integer flag, Integer subNotPassFriend) {
        if (Objects.equals(flag, 0)) {
            this.remove(merId, wxId);
        }
        //
        else if (Objects.equals(flag, 1)) {
            MarketingRewardsBlackListOptDto marketingRewardsBlackListOptDto = new MarketingRewardsBlackListOptDto();
            marketingRewardsBlackListOptDto.setWxid(wxId);
            marketingRewardsBlackListOptDto.setRemark(remark);
            marketingRewardsBlackListOptDto.setMerId(merId);
            marketingRewardsBlackListOptDto.setSubNotPassFriend(subNotPassFriend);
            this.addHandleRemarkIfPresent(marketingRewardsBlackListOptDto);
        }
    }

    public MarketingRewardsBlackListDocument getById(String id) {
        BoolQueryBuilder builder = QueryBuilders.boolQuery().must(QueryBuilders.termQuery("id", id));
        NativeSearchQuery condition = new NativeSearchQueryBuilder().withQuery(builder).build();
        SearchHit<MarketingRewardsBlackListDocument> searchHit = elasticsearchUtil.elasticsearchRestTemplate().searchOne(condition, MarketingRewardsBlackListDocument.class);
        if (Objects.nonNull(searchHit)) {
            return searchHit.getContent();
        }
        return null;
    }

    public MarketingRewardsBlackListDocument getById(String wxId, Long merId) {
        String id = merId + "_" + wxId;
        return this.getById(id);
    }

    @Override
    public Object batchSetSubNotPassFriend(MarketingRewardsBlackListBatchDto batchDto) {

        Iterable<MarketingRewardsBlackListDocument> marketingRewardsBlackListDocuments = marketingRewardsBlackListRepository.findAllById(batchDto.getIds());
        if (ObjectUtils.isEmpty(marketingRewardsBlackListDocuments)) {
            return true;
        }
        int now = (int) (DateTime.now().getTime() / 1000L);
        marketingRewardsBlackListDocuments.forEach(ite -> {
            ite.setSubNotPassFriend(batchDto.getSubNotPassFriend());
            ite.setUpdateTime(now);
        });
        marketingRewardsBlackListRepository.saveAll(marketingRewardsBlackListDocuments);
        return true;
    }
}
